#include "DataSource.h"

DataSource::DataSource()
{
    // set a default database
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    db.open();
}

void DataSource::addTable(const QString& table, bool indexed)
{
//    qDebug() << QString("create table %1 (_eventNr varchar2(100))").arg(table);
    
    QString queryDescription = (indexed ? QString("create table %1 (timestamp integer primary key autoincrement, _eventNr varchar2(100))").arg(table) : QString("create table %1 (_eventNr varchar2(100))").arg(table));
    QSqlQuery query;
    if (!query.exec(queryDescription))
        qDebug() << query.lastQuery() << query.lastError();
    
    QVector<QString> columns;
    columns.append("_eventNr");
    tables[table] = columns;
}

void DataSource::addColumn(const QString& table, const QString& column)
{
//    qDebug() << QString("alter table %1 add %2 varchar2(100)").arg(table).arg(column);
    
    const QString queryString = "alter table " + table + " add " + column + " varchar2(100)";
    QSqlQuery query;
    if (!query.exec(queryString))
        qDebug() << query.lastQuery() << query.lastError();
    
    tables[table].append(column);
}

void DataSource::addRow(const QString& table, const QMap<QString, QString>& values, bool indexed)
{
    if (!tables.contains(table))
        addTable(table, indexed);
    
    QVector<QString> availableColumns = tables[table];
    
    QList<QString> columns = values.keys();
    
    QString columnListing = "(";
    QString valueListing = "(";
    if (values.size() > 0) {
        QString column = columns.at(0);
        QString value = values[column];
        
        if (!availableColumns.contains(column))
            addColumn(table, column);
        
        columnListing.append(column);
        valueListing.append("'");
        valueListing.append(value);
        valueListing.append("'");
    }
    
    for (int i = 1; i < columns.size(); i++) {
        QString column = columns.at(i);
        QString value = values[column];
        
        if (!availableColumns.contains(column))
            addColumn(table, column);
        
        columnListing.append(", ");
        columnListing.append(column);
        
        valueListing.append(", '");
        valueListing.append(value);
        valueListing.append("'");
    }
    columnListing.append(")");
    valueListing.append(")");
    
//    qDebug() << QString("insert into %1 %2 values %3").arg(table).arg(columnListing).arg(valueListing);
    
    const QString queryString = "insert into " + table + " " + columnListing + " values " + valueListing;
    QSqlQuery query;
    if (!query.exec(queryString))
        qDebug() << query.lastQuery() << query.lastError();
}

void DataSource::addUpdateRow(const QString& table, const QMap<QString, QString>& values)
{
    addRow(table, values, true);
}

QMap<QString, QString> DataSource::getRow(const QString& table, const QMap<QString, QString>& constraints)
{
    QMap<QString, QString> values;
    if (!tables.contains(table))
        return values;
    
    QVector<QString> availableColumns = tables[table];

    QString queryDescription = "select * from " + table + " where timestamp = (select max(timestamp) from " + table;
    
    bool isValid = true;
    QMapIterator<QString, QString> constraintsIterator(constraints);
    if (constraintsIterator.hasNext()) 
    {
        constraintsIterator.next();
        queryDescription.append(" where " + constraintsIterator.key() + " = '" + constraintsIterator.value() + "'");
        isValid &= availableColumns.contains(constraintsIterator.key());
        
        while (constraintsIterator.hasNext() && isValid) 
        {
            constraintsIterator.next();
            queryDescription.append(" and " + constraintsIterator.key() + " = '" + constraintsIterator.value() + "'");
            isValid &= availableColumns.contains(constraintsIterator.key());
        }
    }
    
    if (!isValid)
        return values;
    
    queryDescription.append(")");
    
//    qDebug() << queryDescription;
    
    QSqlQuery query(queryDescription);
    query.setForwardOnly(true);
    if (query.next()) {
        QSqlRecord record = query.record();
        for (int column = 0; column < record.count(); column++)
            values[record.fieldName(column)] = record.value(column).toString();
        values.remove("timestamp");
    }
    
    return values;
}

QVector<int> DataSource::eventNumbersForQuery(const QString& queryDescription)
{
	QVector<int> eventNumbers;
	
	QSqlQuery query(queryDescription);
	query.setForwardOnly(true);
	int fieldIndex = -1;
	if (query.next()) {
		if (fieldIndex < 0)
			fieldIndex = query.record().indexOf("_eventNr");
		eventNumbers.append(query.record().value(fieldIndex).toInt());
	}
	
	return eventNumbers;
}

void DataSource::fetchDataForEventNr(int eventNr, QMap<QString, QString>& out)
{
	QSqlQuery query(QString("select * from event where cast(_eventNr as Integer) == %1").arg(eventNr));
	if (query.next()) {
		QSqlRecord record = query.record();
		for (int column = 0; column < record.count(); column++) {
			QString value = record.value(column).toString();
			if (value.length() > 0)
				out[record.fieldName(column)] = value;
		}
		out.remove("timestamp");
	}
}